package com.credithc.signature.job.job;

import com.credithc.signature.common.po.SignatureLog;
import com.credithc.signature.common.utils.DateUtil;
import com.credithc.signature.job.po.Task;
import com.credithc.signature.job.service.InfoService;
import com.credithc.signature.job.service.SignatureService;
import com.credithc.signature.job.workshop.SignatureMaster;
import com.credithc.signature.job.workshop.SignatureWorker;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @desc: <br/>
 * @author: Jingbo Hu<br/>
 * @time：2021年06⽉24⽇<br/>
 * @version：v1.0.0<br>
 */
@Slf4j
@Component
public class ReprocessJob {

    /**
     * 工作线程数
     */
    private static int workerCount = Runtime.getRuntime().availableProcessors();

    @Autowired
    private InfoService infoService;

    @Autowired
    SignatureService signatureService;

    @Value("${signature.channelNo}")
    private String channelNo;

    @Value("${signature.status}")
    private List<Integer> statusList;

    @Value("${signature.timeInterval:5}")
    private Long timeInterval;

    /**
     * 1、定时任务查询失败合同重试
     * 执行逻辑：从request_log表中查询当天失败的合同，并重试
     */
    @XxlJob("reExecuteJobHandler")
    public void reExecuteJobHandler() throws Exception {
        Date endTime = DateUtil.getNowTime();
        Date startTime = DateUtil.getBeforeMinuteByStartTime(timeInterval, endTime);
        log.info("开始执行【未处理成功】定时任务 >>>>>> 现在时间：{} | 任务区间：{} - {}", DateUtil.getDefaultAppointDateStr(endTime), DateUtil.getTimeStr(startTime), DateUtil.getTimeStr(endTime));

        //1、分配任务
        int jobCount = getJobCount(startTime, endTime);
        SignatureMaster master = new SignatureMaster(new SignatureWorker(), workerCount);
        for (int i = 0; i < workerCount; i++) {
            Task task = new Task(i, workerCount, "合同重试【生产者】");
            task.setTaskId(i);
            task.setStartTime(startTime);
            task.setEndTime(endTime);
            task.setChannelNo(channelNo);
            task.setStatusList(statusList);
            master.submit(task);
        }
        // 2、执行任务
        master.execute();
        master.completed();

        // 3、汇总结果
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        while (!master.isCompleted()) {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        if (master.isCompleted()) {
            //计算结果集
            int result = master.getResult();
            stopWatch.stop();
            log.info("结束执行【未处理成功】定时任务 >>>>>> Master总任务数:{} |Workers总任务数:{} |执行耗时: {}秒", jobCount, result, stopWatch.getTotalTimeSeconds());
        }
    }

    /**
     * 获取要执行的任务
     *
     * @param startTime
     * @param endTime
     * @return
     */
    private int getJobCount(Date startTime, Date endTime) {
        Example example = new Example(SignatureLog.class);
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(channelNo)) {
            criteria.andEqualTo("channelNo", channelNo);
        }
        criteria.andGreaterThanOrEqualTo("createTime", startTime)
                .andLessThanOrEqualTo("createTime", endTime)
                .andIn("signStatus", statusList);
        return infoService.selectCountByExample(example);
    }

}
